package org.ourgrid.broker.controlws.gatewayws.transferserver;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

public class TransferUtil {

	private static final String ERROR_TOKEN = "#ERROR#";
	private static final String EOF_TOKEN = "#EOF#";
	
	private static final int PACKET_SIZE = 1024;
	
	public static void writeTransferHeader(TransferHeader header, OutputStream outputStream) throws IOException {
		writeToStream(header.toString(), outputStream);
	}
	
	public static TransferHeader readTransferHeader(InputStream inputStream) throws IOException {
		return TransferHeader.parseHeader(readFromStream(inputStream));
	}
	
	private static void writeToStream(String string, OutputStream outputStream) throws IOException {
		
		byte[] buffer = new byte[PACKET_SIZE];
		byte[] eofBytes = string.getBytes();
		
		for (int i = 0; i < eofBytes.length; i++) {
			buffer[i] = eofBytes[i];
		}
		
		outputStream.write(buffer, 0, PACKET_SIZE);
		
	}
	
	public static void writeToStream(File sourceFile, OutputStream outputStream) throws IOException {
		
		FileInputStream inputStream = null;
		
		try {
			
			inputStream = new FileInputStream(sourceFile);
			
			byte[] buffer = new byte[PACKET_SIZE];
			int len = 0;
			
			while ((len = inputStream.read(buffer, 0, PACKET_SIZE - 1)) != -1) {
				buffer[len] = '\0';
				outputStream.write(buffer, 0, PACKET_SIZE);
			}
			
			writeToStream(EOF_TOKEN, outputStream);
			
			inputStream.close();
			
		} catch (IOException e) {
			writeToStream(ERROR_TOKEN, outputStream);
			throw e;
		} finally {
			if (inputStream != null) {
				inputStream.close();
			}
		}
		
	}
	
	public static String readFromStream(InputStream inputStream) throws IOException {
		
		byte[] buffer = new byte[1024];
		
		if (inputStream.read(buffer) == -1 ) {
			throw new IOException("Could not read from stream");
		}
		
		
		String string = bytesToString(buffer);
		
		return string;
		
	}
	
	public static void writeFromStream(File destinationFile, InputStream inputStream) throws IOException {
		
		FileOutputStream fileOutputStream = null;
		
		try {
			
			fileOutputStream = new FileOutputStream(destinationFile);
			
			byte[] buffer = new byte[PACKET_SIZE];
			
			while (true) {
				
				inputStream.read(buffer);
				
				String packet = bytesToString(buffer);
				if (packet.equals(EOF_TOKEN)) {
					break;
				}
				
				if (packet.equals(ERROR_TOKEN)) {
					throw new IOException("Error while receiving file " + destinationFile);
				}
				
				fileOutputStream.write(buffer, 0, packet.length());
				buffer = new byte[PACKET_SIZE];
			}
			
		} catch (IOException e) {
			throw e;
		} finally {
			if (fileOutputStream != null) {
				fileOutputStream.close();
			}
		}
		
	}
	
	private static String bytesToString(byte[] buffer) {
		byte[] bytes = null;
		
		for (int i = 0; i < buffer.length; i++) {
			if (buffer[i] == '\0') {
				bytes = Arrays.copyOfRange(buffer, 0, i);
				break;
			}
		}
		
		return new String(bytes);
	}
}
